#ifndef _KEYBOARD_H_
#define _KEYBOARD_H_

#include "device/Device.h"

#include <deque>
#include <cassert>
#include <SDL2/SDL.h>

#define KEYBOARD_BASE 0xA0000060
#define KEYBOARD_SIZE 4
#define KEYDOWN_MASK 0x8000

// Note that this is not the standard
#define _KEYS(f) \
	f(ESCAPE) f(F1) f(F2) f(F3) f(F4) f(F5) f(F6) f(F7) f(F8) f(F9) f(F10) f(F11) f(F12) \
	f(GRAVE) f(1) f(2) f(3) f(4) f(5) f(6) f(7) f(8) f(9) f(0) f(MINUS) f(EQUALS) f(BACKSPACE) \
	f(TAB) f(Q) f(W) f(E) f(R) f(T) f(Y) f(U) f(I) f(O) f(P) f(LEFTBRACKET) f(RIGHTBRACKET) f(BACKSLASH) \
	f(CAPSLOCK) f(A) f(S) f(D) f(F) f(G) f(H) f(J) f(K) f(L) f(SEMICOLON) f(APOSTROPHE) f(RETURN) \
	f(LSHIFT) f(Z) f(X) f(C) f(V) f(B) f(N) f(M) f(COMMA) f(PERIOD) f(SLASH) f(RSHIFT) \
	f(LCTRL) f(APPLICATION) f(LALT) f(SPACE) f(RALT) f(RCTRL) \
	f(UP) f(DOWN) f(LEFT) f(RIGHT) f(INSERT) f(DELETE) f(HOME) f(END) f(PAGEUP) f(PAGEDOWN)

#define _KEY_NAME(k) _KEY_##k,

enum {
	_KEY_NONE = 0,
	MAP(_KEYS, _KEY_NAME)
};

#define SDL_KEYMAP(k) keymap[concat2(SDL_SCANCODE_, k)] = concat2(_KEY_, k);

class Keyboard : public Device {
public:
    Keyboard() { MAP(_KEYS, SDL_KEYMAP) }
    bool read(word_t start_addr, size_t length, uint8_t* buffer) override;
    bool write(word_t start_addr, size_t length, const uint8_t* buffer) override;
    void update() override;
private:
    uint32_t keymap[256];
	std::deque<uint32_t> key_queue;
};

#endif
